# encoding: utf-8
#!/usr/local/bin/python2.7
'''
NervuresDesignTool -- Outil de conception/simulation de parapentes Nervures

    Gui Cloison
    -> construit gui Cloison

@author:     Michel Le Berre, Pierre Puiseux    
@copyright:  2013 Nervures. All rights reserved.    
@license:    LGPL
@contact:    be@nervures.com
@deffield    updated: 31 Jan 2013
'''
#import PySide as PyQt4
# import sys
# import numpy as np
# import pickle, cPickle
# from config import DATA_DIR
# from model.basicobjects.glideobject import GlideObject
from PyQt4 import QtGui
from PyQt4 import QtCore
# from PyQt4.uic import loadUiType
# from utilitaires import Path
# from PyQt4.QtGui import (QWidget,)
from PyQt4.QtCore import Qt
from PyQt4.Qt import SIGNAL#, SLOT
# from config import SOURCES_DIR
from utilitaires.utilitaires import trace, alert, p2t, p2s, whoami, baryCentre
#from model.cloison.cloison import Cloison

# from graphics.polygon import NGraphicsPolygonItem
# from graphics.ellipse import NGraphicsEllipseItem 
from graphics.graphicsprofil import EGraphicsProfilItem
from graphics.node import Noeud#, PhantomNode
# from gui.profil.graphicsprofil import NGraphicsProfilItem
# from graphics.graphicscloison import NGraphicsCloisonItem
# from graphics.scene import EGraphicsScene
# from graphics.view import EGraphicsView
from graphics.preferences import PolygonPrefs#, Parametres
# from lecteur import LecteurExameca
from graphics.preferences import ScenePrefs
# from gui.dialogues.dialogues import NDialogChoixProfil, NWidgetChoixProfilSuperposes
#
class EGraphicsScene(QtGui.QGraphicsScene):
    """
    Classe de base
    La scene recoit et traite les évènement (events souris, clavier, ..) transmis par la QGraphicsView, 
    qui les a auparavent convertis en coordonnées scene.
    Elle est le modèle (en terme View/Model).
    Elle peut redéfinir les event-handler (mousePressEvent(),...xxxEvent())  
    Elle les passe ensuite (s'ils ne sont pas redéfinis) je ne sais pas dans quel ordre aux
        - QGraphicsItems concernés-> peuvent accepter ou non les events avec QGraphicsItem.setAcceptXXX()
        - QWidget conteneur -> peuvent réimplémenter les event-handlers
    Les évènements souris sont transmis au 'mouse-grabber' : l'item sur lequel la souris a pressé (sans relacher)
    Les évènements clavier sont trasmis au 'focus-item', l'item qui a le focus (retourné par focusItem())
    """
    prefs = ScenePrefs()
    def __init__(self, parentwidget=None):
        super(EGraphicsScene, self).__init__(parentwidget)
        self.setForegroundBrush(self.prefs.FOREGROUND_BRUSH)
        self.setBackgroundBrush(self.prefs.BACKGROUND_BRUSH)
#         self.setAcceptDrops(True)

        self.insertmode = False
        self.saisiemode = False
        self.showCoord(True)
        self.decal = 0.0
        self.createConnexions()
        self.parentwidget = parentwidget
        self._current = None#ne pas toucher
        self.actionInfos = self.parentwidget.actionInfos
        self.connect(self.actionInfos, SIGNAL('triggered()'), self.infos)
    
    def dropEvent(self, event):
        trace(self, 'event.pos', event.pos())
    
    def infos(self):
        info = self.__str__() 
        try : info = info +'\nClick (scenePos())=%s'%(p2s(self.lastclick[0]))
        except AttributeError : pass
        self.views()[0].showInfos(info)
        
    def __str__(self):
        infos = []
        if not self.selectedItems() :
            nombre = {}
            for item in self.items() :
                trace(self, type(item).__name__)
                if not item.isVisible or item.type() < QtGui.QGraphicsItem.UserType or isinstance(item, Noeud) : 
                    continue
                genre = type(item).__name__ 
                try : nombre[genre] += 1
                except : nombre[genre] = 1
            infos = [u"la scène comporte :"] if nombre else [u"La scène est vide"]    
            infos.extend(['%d <%s>'%(value, key) for key, value in nombre.iteritems()])
        else:
            for item in self.selectedItems() :
                    infos.append(item.__str__())
        return '\n'.join(infos)

    def removeSelectedItems(self):
#         '''
#         '''
        for item in self.selecteduseritems : 
            self.removeItem(item)
    
    def _getSelectedUseritems(self) :
#         trace(self, self.selectedItems())
        return[
               item for item in self.selectedItems()\
               if item.Type>QtGui.QGraphicsItem.UserType
               ]
    selecteduseritems = property(_getSelectedUseritems)

        
    def contextMenuEvent(self, event):
        menu = QtGui.QMenu()
        for item in self.selecteduseritems : 
            for action in item.actions :  
                action.setEnabled(True)
                action.setData(event.scenePos())
                menu.addAction(action)
#         if len(self.selecteduseritems) > 0 :
#             menu.addAction(self.parent().actionSupprimer)
#             menu.addAction(self.parent().actionCopy)
#             menu.addAction(self.parent().actionPaste)
#             menu.addAction(self.parent().actionDupliquer)
#             menu.addSeparator()
        menu.exec_(event.screenPos())
    
    def createConnexions(self):
        self.connect(self, QtCore.SIGNAL('newClick(float, float)'), self.catchCoord)
        self.connect(self, QtCore.SIGNAL('saisieTerminee()'), self.endCatchCoord)
                
    def addShape(self, forme, pos=None):
        gparent = self.gparent
        if forme == 'polyline' : 
#             x0, y0 = gparent.pos().x(), gparent.pos().y()#pos.x(), pos.y()
            self.saisiemode = True
            self.currentpolyline = EGraphicsProfilItem(parent=gparent, posinit=gparent.pos())
            self.currentpolyline.role = 'jonc'
        elif forme == 'polygone' : 
            x0, y0 = pos.x(), pos.y()
            forme = PolygonPrefs.points#un polygone initial defini dans preferences
            forme = [(x0+p[0],y0+p[1]) for p in forme]
            gpoly = EGraphicsProfilItem(points=forme, parent=gparent)
            gpoly.close()
#             gpoly.hardScale(self.corde, (x0, y0))
            gpoly.role = 'renfort'
        elif forme == 'point' : 
            x0, y0 = pos.x(), pos.y()
            point = Noeud((x0, y0), gparent)
            point.role = 'repere'
#         elif forme == 'line' :
#             x0, y0 = pos.x(), pos.y()
#             forme = PolygonPrefs.points[0:2]
#             forme = [(x0+p[0],y0+p[1]) for p in forme]
#             poly = NGraphicsPolygonItem(forme, gcloison)

    def keyPressEvent(self, event):
        key = event.key()
#        trace(self, key)
        modifier = event.modifiers()
        if key in (QtCore.Qt.Key_Escape, ) : 
            self.saisiemode = False
#            trace(self, key)
            self.emit(QtCore.SIGNAL("saisieTerminee()"))
            self.insertmode = False
        elif key == QtCore.Qt.Key_I : 
#             trace(self, key, type(self.parent()))
#             self.parent().actionInfos.trigger()
            self.actionInfos.trigger()

        elif key in (QtCore.Qt.Key_Left,
                     QtCore.Qt.Key_Right,
                     QtCore.Qt.Key_Up,
                     QtCore.Qt.Key_Down, ) :
            if len(self.selectedItems()) == 1 : 
                self.selectedItems()[0].keyPressEvent(event) 
        elif key in (QtCore.Qt.Key_Delete, QtCore.Qt.Key_Backspace,)  : 
            self.removeSelectedItems()
    
        elif key == QtCore.Qt.Key_A  :
#             modifier = QtGui.QApplication.keyboardModifiers()
            if modifier == QtCore.Qt.ControlModifier :
                for item in self.items():
                    item.setSelected(True)
        elif key == QtCore.Qt.Key_Plus:
            self.views()[0].scaleView(1.2)
        elif key == QtCore.Qt.Key_Minus:
            self.views()[0].scaleView(1 / 1.2)
#        elif key == QtCore.Qt.Key_I : 
#            self.actionInfos.trigger()
#        elif key == QtCore.Qt.Key_L : 
#            for item in self.selectedItems() :
#                if isinstance(item, NGraphicsCloisonItem) :
#                    item.action_lisser.trigger()
#        elif key == QtCore.Qt.Key_V : 
#            for item in self.selectedItems() :
#                if isinstance(item, NGraphicsCloisonItem) :
#                    item.actionVerrouiller.trigger()
#        elif key in (QtCore.Qt.Key_Delete, QtCore.Qt.Key_Backspace,)  : 
#            self.removeSelectedItems()
    
#        elif key == QtCore.Qt.Key_A  :
#            modifier = QtGui.QApplication.keyboardModifiers()
#            if modifier == QtCore.Qt.ControlModifier :
#                for item in self.items():
#                    item.setSelected(True)
#        elif key == QtCore.Qt.Key_Plus:
#            self.views()[0].scaleView(1.2)
#        elif key == QtCore.Qt.Key_Minus:
#            self.views()[0].scaleView(1 / 1.2)
        return super(EGraphicsScene, self).keyPressEvent(event)
    
    def mousePressEvent(self, event):
        spos = event.scenePos()#coordonnées scene
        ipos = event.pos()#coordonées item
        self.lastclick = spos, ipos
#        trace(self)
        if self.insertmode and not self.saisiemode :
#            trace(self, 'self.insertmode and not self.saisiemode')
            self.addShape(self.forme_name, spos)
#             self.addShape(self.forme_name, spos)
            return
        elif self.saisiemode :
#            trace(self, 'self.saisiemode')
            return
        return super(EGraphicsScene, self).mousePressEvent(event)
    
    def mouseReleaseEvent(self, event):
        if self.saisiemode : 
#            trace(self)
            posx, posy = p2t(event.scenePos())
#             posx, posy = p2t(event.pos())
            self.emit(QtCore.SIGNAL('newClick(float, float)'), posx, posy)
        return super(EGraphicsScene, self).mouseReleaseEvent(event)
    
    def catchCoord(self, x, y):
        '''Saisir un point à la souris, le tracer'''
#        trace(self, '(x,y)=(%g,%g)'%(x,y))
        self.currentpolyline.appendNode((x,y))
    
    def endCatchCoord(self):
        '''On a fini de saisie les points à la souris, on trace la polyligne'''
#        trace(self, 'self.currentpolyline=%s'%str(self.currentpolyline))
        self.saisiemode = False
#        self.parentwidget.addShape(self.currentpolyline)
        pass
    
    
    def _setInsertMode(self, forme):
        if isinstance(forme, (str, unicode, QtCore.QString)) :
#            trace(self, forme)
            self.forme_name = unicode(forme)
            self._insertmode = True
            return
        try : del self.forme_name
        except AttributeError : pass 
        self._insertmode = False
    
    def _getInsertMode(self):
        return self._insertmode
    insertmode = property(_getInsertMode, _setInsertMode)
    
    def showCoord(self, value):
        self.cursorcontainer = None
        self.cursor = None
        if value : #je change la méthode mouseMoveEvent elle-même qui devient _mouseMoveEvent
            self.mouseMoveEvent = self._mouseMoveEvent
            self.cursorcontainer = QtGui.QGraphicsRectItem(QtCore.QRectF(), parent=None, scene=self)
            self.cursorcontainer.scale(1, -1)
#             self.cursorcontainer.moveBy(1, 0)
            self.cursor = QtGui.QGraphicsSimpleTextItem("0, 0", self.cursorcontainer, self)#; //Fixed at 0, 0
            self.cursor.setFlag(QtGui.QGraphicsItem.ItemIgnoresTransformations)
        else :
            self.mouseMoveEvent = super(EGraphicsScene, self).mouseMoveEvent
    def _mouseMoveEvent(self, event) :
#    // Get the list of the views attached to this scene
        scene_views = self.views()
        for view in scene_views :
#        // get the visible view port
            viewport_widget = view.viewport()
#            // ensure it is visible
            if viewport_widget.isVisible() :
#            // Update cursor position (text to be displayed)
                string = p2s(event.scenePos())
#                self.cursor.setPlainText(string)
                self.cursor.setText(string)
#            // Set the new position of the cursor marche pas, ca sort de l'écran des qu'on fait un recadre()...
#                posx, posy = viewport_widget.width() - self.cursor.boundingRect().width(), viewport_widget.height() - self.cursor.boundingRect().height()
#                self.cursor.setPos(posx, posy)
#                trace(None, posx, posy)
                posx, posy = event.scenePos().x(), -event.scenePos().y()
                self.cursor.setPos(posx, posy)
#                trace(None, event.scenePos())
        super(EGraphicsScene, self).mouseMoveEvent(event)
    
    def recadre(self, marges=0.10):#recadre la scene, pas le widget !
#        marges = 1./4
#        utiliser childrenboundingrect...
        rect = QtCore.QRectF()
        for item in self.items() :
            if item.isVisible() and not isinstance(item, (Noeud,))\
                                and not item == self.cursor\
                                and not item == self.cursorcontainer\
                                and not type(item).__name__ in ('QGraphicsSimpleTextItem'):
                br = item.mapRectToScene(item.boundingRect())
#                 trace(self, br)
                rect = rect | br
                
        #print trace(self), 'scene : ',rect
        X, Y, W, H = rect.left(), rect.top(), rect.width(), rect.height()
        
#         trace(self, 'X, Y, W, H', X, Y, W, H)
        rap = 1.0 #???
        dX, dY = marges*W, rap*marges*H
#        dX, dY = marges*W, marges*H
#        dX, dY = 0, 0#
        
#        trace(self, 'rect : ', rect)
        self.setSceneRect(QtCore.QRectF(X-dX, Y-rap*marges*H, W+2*dX, H+2*dY))
#        self.setSceneRect(QtCore.QRectF(X-dX, Y-dY, W+2*dX, H+2*dY))
#        self.setSceneRect(QtCore.QRectF(X-dX, Y, W+2*dX, H))
#        trace(self, 'scen : ', self.sceneRect())
        self.decal = 1/self.sceneRect().width()
        try : 
            self.removeItem(self.axex)
            self.removeItem(self.axey)
        except AttributeError :
            pass
            
if __name__ == "__main__":
    pass
